<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 重置所有元素的默认样式 */
      * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
      }

      /* 设置页面背景为渐变效果 */
      body {
        min-height: 100vh;
        background-image: linear-gradient(125deg, #1a2a2e, #16243e, #0f3460);
      }

      /* 文本容器，用于放置所有字符元素 */
      .text-container {
        position: absolute;
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        overflow: hidden;
        z-index: -100; /* 置于最底层 */
      }

      /* 单个字符的样式 */
      .char {
        position: absolute;
        font-size: 2.8rem;
        font-weight: bold;
        transform: translate(-50%, -50%); /* 居中定位 */
        transition: transform 0.5s ease-in-out; /* 平滑过渡效果 */
        text-shadow: 0 0 15px #ffffff99; /* 发光效果 */
        will-change: transform; /* 优化动画性能 */
        cursor: default;
        user-select: none; /* 防止文本被选中 */
        pointer-events: none; /* 防止鼠标事件 */
      }

      /* 圆形引导线样式 */
      .cirlce-guide {
        position: absolute;
        border: 2px dashed #ffffff4d; /* 虚线边框 */
        border-radius: 50%;
        transform: translate(-50%, -50%);
        pointer-events: none;
        z-index: 0;
        transform: opacity 0.5s ease;
      }
    </style>

    <link rel="icon" type="image/x-icon" href="../../../favicon.ico" />
</head>
  <body>
    <div class="text-container"></div>
    <script>
      // 动画配置参数
      const TEXT = "卍卍卍卍卍卍卍卍卍"; // 要显示的文本内容
      const BASE_FONT_SIZE = 20; // 基础字体大小
      const ROTATE_SPEED = 0.01; // 旋转速度
      const SMOOTHING = 0.15; // 移动平滑系数（0-1之间，越小越平滑）
      const RT_SMOOTHING = 0.3; // 旋转模式下的平滑系数
      const RAINBOW_SPEED = 0.01; // RGB彩虹色变化速度

      // 获取DOM元素
      const container = document.querySelector(".text-container");

      // 全局变量
      let circleRotateAngle = 0; // 圆形旋转角度
      const chars = []; // 存储所有字符元素的数组
      let mouseX = window.innerWidth + 20; // 鼠标X坐标，初始值在屏幕外
      let mouseY = window.innerHeight + 20; // 鼠标Y坐标，初始值在屏幕外
      let isRotate = false; // 是否处于旋转模式
      let idTimer = null; // 定时器ID
      let circleGuide = null; // 圆形引导线元素
      let hue = 0; // 色相值，用于彩虹色效果

      // 监听鼠标移动事件
      document.addEventListener("mousemove", (e) => {
        mouseX = e.clientX; // 更新鼠标X坐标
        mouseY = e.clientY; // 更新鼠标Y坐标

        // 清除之前的定时器
        clearTimeout(idTimer);

        // 如果当前在旋转模式，先退出旋转模式
        if (isRotate) isRotate = false;

        // 设置新的定时器，500ms后进入旋转模式
        idTimer = setTimeout(() => {
          isRotate = true;
        }, 500);
      });

      // 页面加载完成后初始化
      window.addEventListener("load", () => {
        initChars(); // 初始化字符
        updateChars(); // 开始更新循环
      });

      // 更新圆形引导线
      function updateCircleGuide() {
        if (!circleGuide) return;

        if (isRotate) {
          // 计算圆形半径，根据文本长度动态调整
          const radius = Math.min(
            220, // 最大半径
            Math.max(100, (TEXT.length * BASE_FONT_SIZE) / 2.5) // 最小半径
          );

          // 设置圆形引导线的大小
          circleGuide.style.width = `${radius * 2}px`;
          circleGuide.style.height = `${radius * 2}px`;

          // 设置圆形引导线的位置（跟随鼠标）
          circleGuide.style.left = `${mouseX}px`;
          circleGuide.style.top = `${mouseY}px`;
          circleGuide.style.display = "block"; // 显示引导线
        } else {
          circleGuide.style.display = "none"; // 隐藏引导线
        }
      }

      // 初始化所有字符元素
      function initChars() {
        for (let i = 0; i < TEXT.length; i++) {
          // 创建字符元素
          const char = document.createElement("div");
          char.className = "char";
          char.textContent = TEXT[i];
          char.style.fontSize = `${BASE_FONT_SIZE}px`;

          // 设置初始位置（屏幕外）
          char.dataset.x = window.innerWidth + 20;
          char.dataset.y = window.innerHeight + 20;

          // 应用初始位置
          char.style.left = `${char.dataset.x}px`;
          char.style.top = `${char.dataset.y}px`;

          // 为每个字符设置不同的初始颜色
          const setHue = (i / TEXT.length) * 360;
          char.style.color = `hsl(${setHue}, 100%, 75%)`;

          // 添加到容器并保存到数组
          container.appendChild(char);
          chars.push(char);
        }

        // 创建圆形引导线
        createCircleGuide();
      }

      // 创建圆形引导线元素
      function createCircleGuide() {
        circleGuide = document.createElement("div");
        circleGuide.className = "circle-guide";
        circleGuide.style.display = isRotate ? "block" : "none";
        container.appendChild(circleGuide);
      }

      // 主要的更新函数，处理字符动画
      function updateChars() {
        updateCircleGuide(); // 更新圆形引导线

        if (isRotate) {
          // 旋转模式：字符围绕鼠标做圆周运动
          circleRotateAngle += ROTATE_SPEED; // 增加旋转角度

          // 防止角度值过大
          if (circleRotateAngle % 360 === 0) circleRotateAngle = ROTATE_SPEED;

          // 计算圆形半径
          const radius = Math.min(
            220,
            Math.max(100, (TEXT.length * BASE_FONT_SIZE) / 2.5)
          );

          // 更新每个字符的位置
          chars.forEach((char, index) => {
            const currentX = parseFloat(char.dataset.x);
            const currentY = parseFloat(char.dataset.y);

            // 计算字符在圆上的角度位置
            const angle =
              (index / chars.length) * Math.PI * 2 + circleRotateAngle;

            // 计算字符在圆上的坐标
            const circleX = mouseX + Math.cos(angle) * radius;
            const circleY = mouseY + Math.sin(angle) * radius;

            // 平滑插值到目标位置
            const newX = lerp(currentX, circleX, RT_SMOOTHING);
            const newY = lerp(currentY, circleY, RT_SMOOTHING);

            // 更新字符位置
            char.dataset.x = newX;
            char.dataset.y = newY;
            char.style.left = `${newX}px`;
            char.style.top = `${newY}px`;

            // 计算字符旋转角度，使其垂直于半径
            const wordRotateAngle = angle * (180 / Math.PI) + 90;
            char.style.transform = `translate(-50%, -50%) rotate(${wordRotateAngle}deg)`;

            // 更新彩虹色效果
            hue = (hue + RAINBOW_SPEED) % 360;
            const charHue = ((hue + index / TEXT.length) * 360) % 360;
            char.style.color = `hsl(${charHue}, 100%, 75%)`;
          });
        } else {
          // 跟随模式：字符跟随鼠标移动
          let targetX = mouseX;
          let targetY = mouseY;

          chars.forEach((char, index) => {
            const currentX = parseFloat(char.dataset.x);
            const currentY = parseFloat(char.dataset.y);

            // 平滑插值到目标位置
            const newX = lerp(currentX, targetX, SMOOTHING);
            const newY = lerp(currentY, targetY, SMOOTHING);

            // 更新字符位置
            char.dataset.x = newX;
            char.dataset.y = newY;
            char.style.left = `${newX}px`;
            char.style.top = `${newY}px`;

            // 计算字符旋转角度
            let angle;
            if (index === 0) {
              // 第一个字符朝向鼠标
              angle =
                (Math.atan2(targetY - currentY, targetX - currentX) * 180) /
                  Math.PI +
                90;
            } else {
              // 其他字符朝向相邻的前一个字符
              const prevChar = chars[index - 1];
              const prevX = parseFloat(prevChar.dataset.x);
              const prevY = parseFloat(prevChar.dataset.y);
              angle =
                (Math.atan2(newY - currentY, newX - currentX) * 180) / Math.PI +
                90;
            }

            // 应用旋转变换
            char.style.transform = `translate(-50%, -50%) rotate(${angle}deg))`;

            // 更新彩虹色效果
            hue = (hue + RAINBOW_SPEED) % 360;
            const charHue = ((hue + index / TEXT.length) * 360) % 360;
            char.style.color = `hsl(${charHue}, 100%, 75%)`;

            // 更新下一个字符的目标位置
            targetX = newX;
            targetY = newY;
          });
        }

        // 请求下一帧动画
        requestAnimationFrame(updateChars);
      }

      // 线性插值函数：在两个值之间进行平滑过渡
      function lerp(start, end, t) {
        return start * (1 - t) + end * t;
      }
    </script>
  </body>
</html>
